import os
os.environ["CUDA_VISIBLE_DEVICES"] = '0'
from llamafactory.chat.chat_model import ChatModel
from tqdm import tqdm
import argparse
import json
import sys


output = '/root/autodl-tmp/sft_1209_rank64_train0306_5epoch'
parser = argparse.ArgumentParser(description="Your script description")
parser.add_argument("--model_name_or_path", default="/root/autodl-tmp/Qwen2-7B-Instruct", type=str,
                    help="Model name or path")
parser.add_argument("--adapter_name_or_path", default=output, type=str, help="Checkpoint directory")
parser.add_argument("--template", default="qwen", type=str, help="Template type")
parser.add_argument("--finetuning_type", default="lora", type=str, help="Fine-tuning type")

args = parser.parse_args()
args_dict = vars(args)
chat_model = ChatModel(args_dict)
history = []


with open('submission_testb_all_5epoch0316.json') as f:
     preds1 = f.readlines()

def get_api(name,apis):
    for api in apis:
        if api['name'] == name:
            return api
    return ''
def get_index(data_list):
    for index, sub_list in enumerate(data_list):
        if sub_list:  # 检查子列表是否非空
            # for element in sub_list:
            # print(f"在列表中的索引位置: {index}")
            # print("提取的数据:")
            # print(f"name: {sub_list}")
            return index, sub_list
                # for key, value in element['arguments'].items():
                #     print(f"{key}: {value}")
                # print()
    return False,[]
def validate_api_usage(api_definition, target_calls):
    """
    验证API调用是否符合定义要求，并提供纠正建议和最终正确答案
    
    参数:
        api_definition (dict): API的定义
        target_calls (list): 目标API调用列表
    
    返回:
        dict: 验证结果，包含成功/失败信息、详细信息、纠正建议和最终正确答案
    """
    results = {
        "success": True,
        "errors": [],
        "warnings": [],
        "corrections": [],
        "correct_calls": []  # 存储最终正确的API调用结构
    }
    
    # 提取API定义中的必需参数和属性
    api_name = api_definition.get('name')
    required_params = api_definition.get('parameters', {}).get('required', [])
    properties = api_definition.get('parameters', {}).get('properties', {})
    
    # 遍历目标调用
    for idx, call in enumerate(target_calls):
        call_idx = f"调用 #{idx+1}"
        
        # 创建正确版本的调用结构（深拷贝原始调用）
        correct_call = {
            'name': call.get('name'),
            'arguments': call.get('arguments', {}).copy()
        }
        needs_correction = False
        
        # 检查API名称是否匹配
        if call.get('name') != api_name:
            results["success"] = False
            results["errors"].append(f"{call_idx}: API名称不匹配，应为 '{api_name}'，实际为 '{call.get('name')}'")
            correct_call['name'] = api_name
            needs_correction = True
        
        # 获取调用参数
        call_args = call.get('arguments', {})
        
        # 检查所有必需参数是否存在
        for req_param in required_params:
            if req_param not in call_args:
                results["success"] = False
                results["errors"].append(f"{call_idx}: 缺少必需参数 '{req_param}'")
                # 缺少必要参数，无法提供完整的正确调用
                needs_correction = True
        
        # 检查参数类型
        for param_name, param_value in call_args.items():
            # 检查参数是否在API定义中
            if param_name not in properties:
                results["warnings"].append(f"{call_idx}: 参数 '{param_name}' 不在API定义中")
                continue
                
            expected_type = properties[param_name].get('type')
            
            # 检查类型匹配
            if not check_type(expected_type, param_value):
                results["success"] = False
                actual_type = get_type_name(param_value)
                
                results["errors"].append(f"{call_idx}: 参数 '{param_name}' 应为 {expected_type} 类型，实际为 {actual_type}")
                
                # 尝试纠正
                corrected_value = correct_value(expected_type, param_value)
                if corrected_value is not None:
                    # 记录纠正建议
                    results["corrections"].append({
                        "call_index": idx,
                        "param_name": param_name,
                        "original_value": param_value,
                        "corrected_value": corrected_value,
                        "message": f"参数 '{param_name}' 可修正为: {corrected_value} ({expected_type})"
                    })
                    
                    # 更新正确调用中的参数值
                    correct_call['arguments'][param_name] = corrected_value
                    needs_correction = True
        
        # 如果需要纠正且所有必需参数都存在，则添加到正确调用列表
        missing_required = any(f"{call_idx}: 缺少必需参数" in error for error in results["errors"])
        if needs_correction and not missing_required:
            results["correct_calls"].append(correct_call)
        elif not needs_correction:
            # 如果验证成功，原始调用就是正确的
            results["correct_calls"].append(call)
    
    return results

def check_type(expected_type, value):
    """检查值是否匹配预期的类型"""
    if expected_type == 'string':
        return isinstance(value, str)
    elif expected_type == 'integer':
        return isinstance(value, int)
    elif expected_type == 'number':
        return isinstance(value, (int, float))
    elif expected_type == 'boolean':
        return isinstance(value, bool)
    elif expected_type == 'array':
        return isinstance(value, list)
    elif expected_type == 'object':
        return isinstance(value, dict)
    return False

def get_type_name(value):
    """获取值的类型名称"""
    if isinstance(value, str):
        return 'string'
    elif isinstance(value, int):
        return 'integer'
    elif isinstance(value, float):
        return 'number'
    elif isinstance(value, bool):
        return 'boolean'
    elif isinstance(value, list):
        return 'array'
    elif isinstance(value, dict):
        return 'object'
    return type(value).__name__

def correct_value(expected_type, value):
    """尝试将值转换为预期类型"""
    try:
        if expected_type == 'string':
            return str(value)
        elif expected_type == 'integer':
            if isinstance(value, str) and value.isdigit():
                return int(value)
            elif isinstance(value, float):
                return int(value)
        elif expected_type == 'number':
            if isinstance(value, str) and value.replace('.', '', 1).isdigit():
                return float(value)
        elif expected_type == 'boolean':
            if isinstance(value, str):
                if value.lower() in ('true', 'yes', '1', 'y'):
                    return True
                elif value.lower() in ('false', 'no', '0', 'n'):
                    return False
    except (ValueError, TypeError):
        pass
    return None

# 示例数据
api = {
    'name': 'query_token_balance',
    'description': '查询指定地址在特定区块链上的代币余额。',
    'parameters': {
        'type': 'object',
        'properties': {
            'wallet_address': {'type': 'string', 'description': '钱包的区块链地址'},
            'token_contract_address': {'type': 'string', 'description': '代币的智能合约地址'},
            'network': {'type': 'string', 'description': '区块链网络名称'},
            'include_usd_value': {'type': 'boolean', 'description': '是否包含以美元计算的余额价值', 'default': False},
            'decimals': {'type': 'integer', 'description': '代币的小数位数，用于正确显示余额'}
        },
        'required': ['wallet_address', 'token_contract_address', 'network']
    }
}

# 错误类型示例 - 有意引入一些类型错误
target_with_errors = [
    {
        'name': 'query_token_balance',
        'arguments': {
            'wallet_address': 'bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq',
            'token_contract_address': '0x6B175474E89094C44Da98b954EedeAC495271d0F',
            'network': 'Bitcoin',
            'include_usd_value': 'yes',  # 应该是布尔值
            'decimals': '18'  # 应该是整数
        }
    }
]

# 验证API调用
validation_result = validate_api_usage(api, target_with_errors)
# 添加打印最终正确答案
if validation_result["correct_calls"]:
    print("\n最终正确答案:")
    import json
    print(json.dumps(validation_result["correct_calls"], indent=2, ensure_ascii=False))

import json
with open('result_5epoch_0314.jsonl') as f:
     preds = f.readlines()
preds[0]

with open('submission_testb_all_5epoch0306_model0306.json') as f:
     preds1 = f.readlines()

with open('submission_testb_all_5epoch0316_seed8888.json') as f:
     preds2 = f.readlines()

with open('submission_testb_all_5epoch0316.json') as f:
     preds3 = f.readlines()

with open('submission_testb_all_5epoch0316_1e-4.json') as f:
     preds4 = f.readlines()
    
def flatten_nested_predictions(nested_predictions):
    """
    将嵌套的模型预测结果展平为单一列表
    
    参数:
    nested_predictions: 包含嵌套列表的预测结果
    
    返回:
    展平后的单一列表，包含所有非空列表中的项目
    """
    flattened_result = []
    
    # 遍历最外层列表
    for sublist in nested_predictions:
        # 如果是非空列表，将其中的所有项目添加到结果中
        if isinstance(sublist, list) and sublist:
            flattened_result.extend(sublist)
    
    return [flattened_result]

def flatten_nested_predictions1(nested_predictions):
    """
    将嵌套的模型预测结果展平为单一列表
    
    参数:
    nested_predictions: 包含嵌套列表的预测结果
    
    返回:
    展平后的单一列表，包含所有非空列表中的项目
    """
    flattened = [[]]
    flattened_result = []
    nested_predictions= nested_predictions[1:]
    # 遍历最外层列表
    for sublist in nested_predictions:
        # 如果是非空列表，将其中的所有项目添加到结果中
        if isinstance(sublist, list) and sublist:
            flattened_result.extend(sublist)
    flattened.append(flattened_result)
    return flattened

def flatten_nested_predictions2(nested_predictions):
    """
    将嵌套的模型预测结果展平为单一列表
    
    参数:
    nested_predictions: 包含嵌套列表的预测结果
    
    返回:
    展平后的单一列表，包含所有非空列表中的项目
    """
    flattened = [[]]
    flattened_result = []
    nested_predictions= nested_predictions[:-1]
    # 遍历最外层列表
    for sublist in nested_predictions:
        # 如果是非空列表，将其中的所有项目添加到结果中
        if isinstance(sublist, list) and sublist:
            flattened_result.extend(sublist)
    flattened=[flattened_result]
    flattened.append([])
    return flattened

nested_predictions = json.loads(preds[12])['targets'] 
# 展平预测结果
flattened_result = flatten_nested_predictions(nested_predictions)

# 打印结果
import json
print(json.dumps(flattened_result, indent=2))


import re

def is_chinese_and_punctuation(text):
    """
    判断字符串是否全部由中文字符和标点符号组成
    
    Args:
        text: 需要检查的字符串
        
    Returns:
        布尔值，如果全部由中文和符号组成返回True，否则返回False
    """
    if not text:  # 检查空字符串
        return False
    
    # 使用正则表达式匹配中文字符和中文/英文标点符号
    # \u4e00-\u9fff 是中文字符的Unicode范围
    # \u3000-\u303f 是中文标点符号
    # \uff00-\uffef 是全角字符，包括中文标点
    # \u0020-\u007f 是ASCII码范围内的字符（英文标点等）
    pattern = r'^[\u4e00-\u9fff\u3000-\u303f\uff00-\uffef\u0020-\u007f]+$'
    
    # 检查是否至少含有一个中文字符
    has_chinese = bool(re.search(r'[\u4e00-\u9fff]', text))
    
    # 检查整个字符串是否只包含中文和符号
    only_chinese_and_punct = bool(re.match(pattern, text))
    
    # 同时满足两个条件：包含中文字符且只由中文和符号组成
    return has_chinese and only_chinese_and_punct

# 更严格的版本：只允许中文字符和中文标点
def is_strictly_chinese(text):
    """
    判断字符串是否严格由中文字符和中文标点符号组成（不包含英文和数字）
    """
    if not text:
        return False
    
    # 只匹配中文字符和中文标点
    pattern = r'^[\u4e00-\u9fff\u3000-\u303f\uff00-\uffef]+$'
    
    # 检查是否至少含有一个中文字符
    has_chinese = bool(re.search(r'[\u4e00-\u9fff]', text))
    
    # 检查整个字符串是否只包含中文和中文标点
    only_chinese_and_punct = bool(re.match(pattern, text))
    
    return has_chinese and only_chinese_and_punct

# 测试
test_strings = [
    "这是一个中文字符串",
    "这是带符号的中文，你好！",
    "这是带英文的Chinese混合字符串",
    "这里有数字123",
    "！@#￥%……&*（）",
    "Hello World!",
    ""  # 空字符串
]

for s in test_strings:
    print(f'"{s}" 是否只包含中文和符号: {is_chinese_and_punctuation(s)}')
    print(f'"{s}" 是否严格只包含中文和中文符号: {is_strictly_chinese(s)}')


def validate_api_parameters(api, user_messages):
    """
    检查API参数是否在用户消息历史中出现
    
    参数:
    api (dict): 包含API名称和参数的字典
    user_messages (list): 用户历史消息列表
    
    返回:
    dict: 清理后的API，如果参数不在历史消息中则删除相应参数
    """
    # 创建API的副本以避免修改原始数据
    validated_api = api.copy()
    arguments = api.get("arguments", {}).copy()
    validated_arguments = {}
    
    # 将所有用户消息合并为一个大字符串，方便检查
    all_messages = " ".join(user_messages).lower()
    
    # 检查各参数是否在用户消息中出现
    for key, value in arguments.items():
        if isinstance(value, bool):
            continue

        # if  isinstance(value, array):
        #     continue
        if  isinstance(value, list):
            continue
        # 将值转换为字符串
        value_str = str(value)
        
        # 检查参数值是否在用户消息中
        if value_str.lower() in all_messages:
            validated_arguments[key] = value
    
    # 更新API对象
    validated_api["arguments"] = validated_arguments
    
    return validated_api

def is_all_chinese(text):
    """
    判断字符串是否全部由中文字符组成
    
    Args:
        text: 要检查的字符串
    
    Returns:
        bool: 如果字符串全部由中文字符组成则返回True，否则返回False
    """
    if not text:
        return False
    
    for char in text:
        if not '\u4e00' <= char <= '\u9fff':
            return False
    
    return True



def check_api_params_in_messages(api, user_messages):
    # Extract the arguments from the API
    api_name = api.get("name", "")
    api_args = api.get("arguments", {}).copy()  # Make a copy to avoid modifying during iteration
    
    # Create a string of all user messages combined
    all_messages = " ".join(user_messages).lower()
    
    # Check each argument value against user messages
    params_to_remove = []
    for param, value in api_args.items():
        # Skip boolean values
        if isinstance(value, bool):
            continue

        if isinstance(value, str) and len(value) == 10 and value[4] == '-' and value[7] == '-':
            try:
                # Check if it's a valid date format
                year, month, day = value.split('-')
                if len(year) == 4 and len(month) == 2 and len(day) == 2:
                    continue
            except:
                pass

        if isinstance(value, str) and is_chinese_and_punctuation(value):
            continue

        if isinstance(value, str) and ',' in str(value):
            continue
        
        if (isinstance(value, float) or isinstance(value, int)) and ('0.' in str(value) or '-' in str(value) ):
            try:
                # Check if it's a valid date format
                
                    continue
            except:
                pass
        if 'level' in param:
            continue

        # if '万' in all_messages or '%' in all_messages or '千' in all_messages or '百' in all_messages or '年' in all_messages or '月' in all_messages or '1GB' in all_messages or '@' in all_messages or '小时' in all_messages :
            continue

        if isinstance(value, int ) and value in [1,2,3,4,5]:
            continue
        
        if isinstance(value, list):
            continue
        if isinstance(value, dict):
            continue
        # Handle list values
        if isinstance(value, list):
            # Check if any list item is not in the messages
            should_remove = False
            for item in value:
                item_str = str(item).lower()
                if item_str not in all_messages:
                    should_remove = True
                    break
            if should_remove:
                params_to_remove.append(param)
        # Handle dictionary values
        elif isinstance(value, dict):
            # Check if any dict value is not in the messages
            should_remove = False
            for dict_key, dict_value in value.items():
                dict_value_str = str(dict_value).lower()
                if dict_value_str not in all_messages:
                    should_remove = True
                    break
            if should_remove:
                params_to_remove.append(param)
        else:
            # Convert value to string and lowercase for comparison
            value_str = str(value).lower()
            # Check if the value is not present in any user message
            if value_str not in all_messages:
                params_to_remove.append(param)
    
    # Remove parameters that were not found in user messages
    result_args = api_args.copy()
    for param in params_to_remove:
        del result_args[param]
    
    # Return the updated API
    return {
        "name": api_name,
        "arguments": result_args
    }

# Example usage

# 测试代码

# 测试数据
api = {'name': 'classroom_attendance_tracker', 'arguments': {'class_id': 'class_202', 'student_ids': ['stu_004', 'stu_005'], 'date': '2023-10-02', 'attendance_status': ['present', 'present']}}

user_messages =  ['创业公司智慧园大厦装修预算如何控制？', '我想查看一下2023-10-02的考勤情况。', '关于class_202的考勤记录，你能帮我查一下吗？', 'stu_004和stu_005在当天的考勤状态是present和present。', '我这里有一份关于市场营销的文档，麻烦帮我总结一下主要内容。']

result = check_api_params_in_messages(api, user_messages)
print("原始API:", api)
print("验证后API:", result)

# 显示哪些参数被删除了
original_params = set(api["arguments"].keys())
validated_params = set(result["arguments"].keys())
removed_params = original_params - validated_params
if removed_params:
    print("被删除的参数:", removed_params)
else:
    print("没有参数被删除")


num=0
num1=0
num2=0
new_preds=[]
with open('result_5epoch_0318_process.jsonl', 'w', encoding='utf-8') as file:
    for i in range(len(preds)):
        d = json.loads(preds[i])
        apis = d['apis']
        user_messages = d['user_messages']
        
        targets = d['targets']
        if len(targets)!=len(user_messages) and len(targets)!=0:
            
            if len(user_messages)==1:
                nested_predictions = d['targets'] 
                # 展平预测结果
                flattened_result = flatten_nested_predictions(nested_predictions)
                d['targets'] = flattened_result
                if len(flattened_result)!=len(user_messages):
                    # print(flattened_result, len(targets),len(user_messages),i)
                    num2+=1
                
            elif len(user_messages)==2:
                if targets[0]==[]:
                    nested_predictions = d['targets'] 
                    flattened_result = flatten_nested_predictions1(nested_predictions)
                    d['targets'] = flattened_result
                    
                    num+=1
                elif targets[-1]==[]:
                    nested_predictions = d['targets'] 
                    flattened_result = flatten_nested_predictions2(nested_predictions)
                    d['targets'] = flattened_result
                    # print(targets,'\n*****************\n',flattened_result,len(flattened_result),len(user_messages),i)
        elif len(targets)==0:
            print(json.loads(preds1[i])['target'],i)
            num1+=1
        targets = d['targets']
        if len(targets)!=len(user_messages) and len(targets)!=0:
            print(len(targets),len(user_messages),i)
            num2+=1

        if len(targets)>20:
            print(targets,len(user_messages),i)
            num2+=1
        
        new_preds.append(d)
        json_line = json.dumps(d, ensure_ascii=False)
        # 将 JSON 字符串写入文件，并添加换行符
        file.write(json_line + '\n')


